/**
 * 
 * @project : privateNotes
 * 
 * @file: RXFileSystem.js
 * 
 * @author: appPro-01
 * 
 * @created_date : Wednesday, April 17th 2019, 6:03:26 pm
 * --------------------------------------------------
 * @last_modified : appPro-01
 * @modified_by : Friday, April 26th 2019, 11:53:13 pm
 * 
 * --------------------------------------------------
 * 
 * MIT License
 * 
 * Copyright (c) 2019 appPro
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * 
 * --------------------------------------------------
 * 
 * @fileoverview: `json etc, create-file 数据持久化`
 * @requires [react-native-fs] => https://github.com/itinance/react-native-fs
 * 
 * @flow
 * 
 * 
 * @blog http://www.cnblogs.com/jackson-zhangjiang/p/9554611.html
 * 
 *       https://java.ctolib.com/article/wiki/51456
 * 
 * 可以参考 react-native-filesystem
 * https://github.com/benwixen/react-native-filesystem
 * 
 */

'use strict'

import { Platform } from 'react-native'
import RNFS from 'react-native-fs'
import RXCacheKey from './RXCacheKey'


const isIphone = Platform.OS === 'ios';
const RXF_WARN = 'RXFileSystem error =>'

class RXFileSystem {
  
  static PATH_cache = 'cache'
  static isIOS = isIphone;

  static getDirectoryPath() {
    if(isIphone) {
      return RNFS.DocumentDirectoryPath
    }
    return RNFS.DocumentDirectoryPath  
  }

  static getCachePath = () => {
    if(isIphone) {
      return RNFS.CachesDirectoryPath
    }
    return RNFS.TemporaryDirectoryPath
  }

  static getPath(pathOptions=RXCacheKey.TYPE_lib) {
    var path = ''
    if(pathOptions === RXCacheKey.TYPE_cache) {
      path = this.getCachePath();
    }
    else {
      path = this.getDirectoryPath();
    }
    path = path+'/'+RXCacheKey.ROOT_path;
    return path;
  }

  static writeFile(filePath=null, contents=null, encode='utf8', pathOptions=RXCacheKey.TYPE_lib, callBack=null) {
    
    /** 1、文件名是否存在 */
    if(!filePath || (typeof filePath) !== 'string' || filePath.length < 1)  {
      console.warn(RXF_WARN + 'writeFile()=> fileName = null')
      return;
    }
    /** 2、内容是否存在 */
    if(!contents || contents.length<1 ) {
      console.warn(RXF_WARN + 'writeFile()=> contents = null')
      return;
    }
    
    encode = encode || 'utf8';
    pathOptions = pathOptions || RXCacheKey.TYPE_lib;

    /** 3、fileName 不用关心扩展名 */
    var path = this.getPath(pathOptions)
    if(path.length < 1) {
      console.warn(RXF_WARN + 'writeFile()=> path = null')
      return;
    }
    path = path +'/'+filePath;
    console.log('path', path);

    this.createDir(
      path,
      (success)=>{
        if(success) {
        this.private_writeFile(path, contents, encode, callBack);
        }
        else {
          console.warn('writeFile() => write fail ....')
          if(callBack) {
            callBack(false)
          }
        }
      }
    ); 
  }

  static createDir(filePath=null, callBack=null) {
    if(!filePath) {
      console.log(' fileExists() filePath=null');
      if(callBack) {
        callBack(false);
      }
      return;
    }
    var obj = filePath.lastIndexOf("/");
    if(obj < 1) {
      console.log(' fileExists() filePath=null => filePath='+filePath);
      if(callBack) {
        callBack(false);
      }
      return;
    }
    // let fileName = filePath.split('/').pop()
    let directory = filePath.substr(0, obj);
    if(!directory || directory.length < 1) {
      console.log(' fileExists() directory=null => directory='+filePath);
      if(callBack) {
        callBack(false);
      }
      return;
    }

    console.log('directory=>'+directory)

    RNFS.mkdir(directory)
    .then(()=>{
      console.log('mkdir[0 - then ] create directory success =>'+directory)
      if(callBack) {
        callBack(true);
      }
    })
    .catch((err)=>{
      console.log('mkdir[1 - then ] 【error】create directory fail =>'+err.message)
      if(callBack) {
        callBack(false);
      }
    });
  }

  static readFile(filePath=null, encode='utf8', pathOptions=RXCacheKey.TYPE_lib, callBack) {
    encode = encode || 'utf8';
    pathOptions = pathOptions || RXCacheKey.TYPE_lib;
    /** 1、文件名是否存在 */
    if(!filePath || (typeof filePath) !== 'string' || filePath.length < 1)  {
      console.warn(RXF_WARN + 'readFile()=> fileName = null')
      if(callBack) {
        callBack(false, null)
        // callBack(false) //这么写也可以
      }
      return;
    }
 
    /** 2、filePath[fileName] 不用关心扩展名 */
    var path = this.getPath(pathOptions)+'/'+filePath;

    this.createDir(
      path,
      (success)=>{
        if(success) {
          this.private_readFile(path, callBack);
        }
        else {
          console.warn('readFile() => createDir fail ....')
          if(callBack) {
            callBack(false, null)
          }
        }
      }
    )
  }

  static private_writeFile(filePath=null, contents=null, encode='utf8', callBack=null) {
    RNFS.writeFile(filePath, contents, encode)
    .then(() => {
      console.log('write success => filePath'+filePath);
      if(callBack) {
        callBack(true)
      }
    })
    .catch((err) => {
        console.warn(RXF_WARN + 'writeFile()=> writeFile() =>'+ err.message)
        if(callBack) {
          callBack(false)
        }
    });
  }

  static private_readFile(filePath=null, callBack){
    RNFS.readFile(filePath)
    .then((result) => {
      console.log(result);
      if(callBack) {
        callBack(true, result)
      }
    })
    .catch((err) => {
        console.warn(RXF_WARN + 'readFile()=> '+ err.message)
        if(callBack) {
          callBack(false, null)
        }
    });
  }

  /**
   * 删除文件
   * 
   * @param {*} filePath 
   * @param {*} pathOptions 
   * @param {*} callBack 
   */
  static deleteFile(filePath=null, pathOptions=RXCacheKey.TYPE_lib, callBack) {
    pathOptions = pathOptions || RXCacheKey.TYPE_lib;

    var isFilepath = false;
    if(!filePath || (typeof filePath !== 'string') || !filePath.length) {
      console.log('deleteFile() => filePath=null');
      if(callBack) {
        callBack(false, isFilepath, null);
      }
      return;
    }

    var path = this.getPath(pathOptions)+'/'+filePath;

    RNFS.exists(path)
    .then((flag)=>{
      if(flag) {
        RNFS.unlink(path)
        .then(()=>{
          isFilepath = true;
          console.log('deleteFile() => success => filePath'+path);
          if(callBack) {
            callBack(true, isFilepath, null);
          }
        })
        .catch((err)=>{
          if(callBack) {
            let msg = err.message || '';
            callBack(false, isFilepath, msg);
          }
        })
      }
    })
    .catch((err)=>{
      if(callBack) {
        callBack(false, isFilepath, null);
      }
    });
  }

  static readDir(path, pathOptions=RXCacheKey.TYPE_lib, callBack) {
    var isFilepath = false;
    if(!filePath || (typeof filePath !== 'string') || !filePath.length) {
      console.log('readFilesWithPath() => filePath=null');
      if(callBack) {
        callBack(false, isFilepath, null);
      }
      return;
    }

    var path = this.getPath(pathOptions)+'/'+filePath;
    // get a list of files and directories in the main bundle
    RNFS.readDir(path) // On Android, use "RNFS.DocumentDirectoryPath" (MainBundlePath is not defined)
    .then((result) => {
      console.log('GOT RESULT', result);

      // stat the first file
      return Promise.all([RNFS.stat(result[0].path), result[0].path]);
    })
    .then((statResult) => {
      if (statResult[0].isFile()) {
        // if we have a file, read it
        return RNFS.readFile(statResult[1], 'utf8');
      }

      return 'no file';
    })
    .then((contents) => {
      // log the file contents
      console.log(contents);
    })
    .catch((err) => {
      console.log(err.message, err.code);
    });
  }
}



export default RXFileSystem;


/**
 * API
 * 
 * (not available on Android)
 * MainBundlePath (String) The absolute path to the main bundle directory 
 * 
 * DocumentDirectoryPath (String) The absolute path to the document directory
 * 
 * 
 * 
 * 
 * (falls back to Caching-Directory on Android)
 * TemporaryDirectoryPath (String) The absolute path to the temporary directory 
 * 
 * (android only) 需要配置权限
 * ExternalStorageDirectoryPath (String) The absolute path to the external storage, shared directory 
 * 
 * 
 * 
 * (iOS only)
 * LibraryDirectoryPath (String) The absolute path to the NSLibraryDirectory 
 * 
 * (android only)
 * ExternalDirectoryPath (String) The absolute path to the external files, shared directory 
 * 
 * 
 * 
 * 
 * CachesDirectoryPath (String) The absolute path to the caches directory
 * 
 * (android only)
 * ExternalCachesDirectoryPath (String) The absolute path to the external caches directory 
 * 
 * 
 * 
 * 


  Library 目录：这个目录下有两个子目录：
  3.1 Preferences 目录：包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件，
                  而是应该使用NSUserDefaults类来取得和设置应用程序的偏好.
  3.2 Caches 目录：用于存放应用程序专用的支持文件，保存应用程序再次启动过程中需要的信息。
          可创建子文件夹。可以用来放置您希望被备份但不希望被用户看到的数据。该路径下的文件夹，
          除Caches以外，都会被iTunes备份。

 */
